`timescale 1ns/1ps

module tb_IIR_single_stage();

// 定义模块参数
parameter datin_width = 14;
parameter daout_width = 14;
parameter coeffct_width = 20;
parameter b0 = 21;
parameter b1 = -24;
parameter b2 = 21;
parameter a0 = 2048;
parameter a1 = -3335;
parameter a2 = 1370;

// 生成时钟和复位信号
reg clk;
reg rst_n;

// 输入信号寄存器
reg signed [datin_width-1:0] Xin;
reg signed [datin_width-1:0] Xin1_reg, Xin2_reg;
reg signed [daout_width-1:0] Yin1_reg, Yin2_reg;

// 输出信号线
wire signed [datin_width-1:0] Xin1_save, Xin2_save;
wire signed [daout_width-1:0] Yout;
wire signed [datin_width-1:0] Yin1_save, Yin2_save;

// 生成 100MHz 时钟
initial begin
    clk = 0;
    forever #5 clk = ~clk; // 每10ns翻转，周期20ns
end

// 生成复位信号
initial begin
    rst_n = 0;        // 初始复位
    Xin = 12'd0;     // 初始输入信号为0
    #25 rst_n = 1;    // 25ns后释放复位
    #10
    Xin = 12'd1;
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd4000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd1;  
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd4000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd1;  
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd4000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd1;  
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd4000;
    #10
    Xin = 12'd3000;
    #10
    Xin = 12'd2000;
    #10
    Xin = 12'd1000;
    #10
    Xin = 12'd1;  
end

// 输入激励和寄存器更新逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // 复位初始化
        Xin1_reg <= 12'd0;
        Xin2_reg <= 12'd0;
        Yin1_reg <= 12'd0;
        Yin2_reg <= 12'd0;
    end else begin
        // 更新延迟寄存器
        Xin2_reg <= Xin2_save;
        Xin1_reg <= Xin1_save;
        Yin2_reg <= Yin2_save;
        Yin1_reg <= Yin1_save;
    end
end

// 实例化被测模块
IIR_single_stage #(
    .datin_width(datin_width),
    .daout_width(daout_width),
    .coeffct_width(coeffct_width),
    .b0(b0),
    .b1(b1),
    .b2(b2),
    .a0(a0),
    .a1(a1),
    .a2(a2)
) uut (
    .Xin(Xin),
    .Xin1(Xin1_reg),
    .Xin2(Xin2_reg),
    .Xin1_save(Xin1_save),
    .Xin2_save(Xin2_save),
    .Yin1(Yin1_reg),
    .Yin2(Yin2_reg),
    .Yout(Yout),
    .Yin1_save(Yin1_save),
    .yin2_save(Yin2_save)
);

// 波形记录
initial begin
    $dumpfile("iir_filter.vcd");
    $dumpvars(0, tb_IIR_single_stage);
end

// 仿真时长控制
initial begin
    #500 $display("Simulation finished");
    $finish;
end

endmodule